package agent_logic

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"sync"
	"yunzhan/common/utils"
	agent "yunzhan/rpc-server/pb"

	"yunzhan/api-server/internal/svc"
	"yunzhan/api-server/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type DeleteAgentLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewDeleteAgentLogic 删除agent
func NewDeleteAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteAgentLogic {
	return &DeleteAgentLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *DeleteAgentLogic) DeleteAgent(req *types.DeleteAgentRequest) (resp *types.DeployResponse, err error) {
	if req.Nodes == nil || len(req.Nodes) == 0 {
		return &types.DeployResponse{
			Code:    500,
			Message: "未配置节点信息, 无法执行删除Agent操作",
		}, errors.New("未配置节点信息, 无法执行删除Agent操作")
	}

	var wg sync.WaitGroup
	results := make(chan *NodeResult, len(req.Nodes))
	var mu sync.Mutex

	parallelism := l.svcCtx.Config.Parallelism
	if (parallelism <= 0) || (parallelism > len(req.Nodes)) {
		parallelism = len(req.Nodes)
	}
	sem := make(chan struct{}, parallelism)

	for _, node := range req.Nodes {
		wg.Add(1)
		sem <- struct{}{}
		go func(n *agent.NodeInfo) {
			defer func() {
				<-sem
				wg.Done()
			}()
			result := &NodeResult{
				Host:    n.Host,
				Success: true,
				Message: "删除agent成功",
			}

			err = l.deleteAgentFromNode(n, req.ClusterID)
			if err != nil {
				result.Success = false
				result.Message = fmt.Sprintf("删除agent失败: %v", err)
			}

			mu.Lock()
			results <- result
			mu.Unlock()
		}(node)
	}

	go func() {
		wg.Wait()
		close(results)
	}()

	var nodeResults []*NodeResult
	for result := range results {
		nodeResults = append(nodeResults, result)
	}

	jsonData, err := json.Marshal(nodeResults)
	if err != nil {
		return &types.DeployResponse{
			Code:    500,
			Message: fmt.Sprintf("删除agent操作失败: %v", err),
		}, err
	}

	return &types.DeployResponse{
		Code:    200,
		Message: fmt.Sprintf("删除agent操作完成, %s", string(jsonData)),
	}, nil
}

func (l *DeleteAgentLogic) deleteAgentFromNode(n *agent.NodeInfo, clusterID string) error {
	// 检查节点是否存在
	var count int
	querySql := fmt.Sprintf("SELECT COUNT(1) FROM %s WHERE agent_id = ? AND hostname = ? AND cluster_id = ?", l.svcCtx.Config.Mysql.Tables.AgentHeartbeats)
	err := l.svcCtx.Conn.QueryRowCtx(l.ctx, &count, querySql, n.AgentId, n.Host, clusterID)
	if err != nil {
		return fmt.Errorf("数据库查询数据失败, 节点: %s, %v", n.Host, err)
	}

	if count == 0 {
		return fmt.Errorf("无法执行删除agent操作, 数据库中无 %s 节点信息", n.Host)
	}

	pool := utils.NewSSHConnectionPool(n.Host, n.Port, n.Username, n.Password, 10)
	client, err := pool.GetConnection()
	if err != nil {
		return fmt.Errorf("创建 ssh 连接池异常: %v, output: %s", n.Host, err)
	}
	defer pool.ReleaseConnection(client)

	session, err := client.NewSession()
	if err != nil {
		return fmt.Errorf("创建 ssh session 异常: %v, output: %s", n.Host, err)
	}
	defer session.Close()

	// 停止agent服务
	stopCommand := fmt.Sprintf("/usr/bin/sudo systemctl disable agent-server.service --now")
	output, err := session.CombinedOutput(stopCommand)
	if err != nil {
		return fmt.Errorf("%s: 停止Agent服务失败: %v, output: %s", n.Host, err, string(output))
	}

	// 删除元数据库中节点信息
	deleteSql := fmt.Sprintf("DELETE FROM %s WHERE agent_id = ? AND hostname = ? AND cluster_id = ?", l.svcCtx.Config.Mysql.Tables.AgentHeartbeats)
	_, err = l.svcCtx.Conn.ExecCtx(l.ctx, deleteSql, n.AgentId, n.Host, clusterID)
	if err != nil {
		return fmt.Errorf("数据库删除Agent失败: %v, 节点: %s", err, n.Host)
	}

	return nil
}

type NodeResult struct {
	Host    string `json:"host"`
	Success bool   `json:"success"`
	Message string `json:"message"`
}
